﻿#include "mythread.h"
#include <QHostAddress>
#include <QJsonDocument>
#include <QApplication>
#include <QThread>
#include <QEventLoop>   // 事件循环类

MyThread::MyThread(TransferType type,
                   const QString &fromname,
                   const QString &filepath,
                   const QString &filename,
                   const QString button,
                   const int startChunk,
                   const QString &host,
                   quint16 port,
                   QThread *parent)
    : QThread(parent),
      transferType(type),
      fromName(fromname),
      filePath(filepath),
      fileName(filename),
      Button(button),
      startChunk(startChunk),
      isConnected(false),
      flag(0)
{
    socket = new QTcpSocket();
    socket->connectToHost(host, port);
    connect(socket, &QTcpSocket::connected, this, &MyThread::onConnected);

    if (transferType == Upload)
    {
        file.setFileName(filePath);
        fileSize = file.size();
        if(!file.open(QIODevice::ReadOnly))
        {
            qDebug() << "Failed to open file: " << filepath;
            return;
        }
    }
}

MyThread::~MyThread()
{
    quit();
    wait();
//    delete socket;
}

void MyThread::run()
{
//    QEventLoop loop;

#if 1
    exec();
#else
    int cnt = 0;
    while (1)
    {
        if (isConnected == true)
        {
            break;
        }
        QThread::msleep(1000);
        cnt++;
        qDebug() << "cnt:" << cnt << endl;
    }

    if(transferType == Upload)
    {
        totalChunks = static_cast<int>(fileSize / chunkSize);
        if (fileSize % chunkSize != 0)
        {
            totalChunks++;
        }
        qDebug() << totalChunks << endl;

        int startChunk = this->startChunk;
        qDebug() << startChunk << endl;
        file.seek(startChunk * chunkSize);

        for (int i = startChunk; i < totalChunks; i++)
        {
            qDebug() << i << endl;
            QByteArray chunk = file.read(chunkSize);
            QJsonObject obj;
            obj["flag"] = 7;
            obj["fromname"] = fromName;
            obj["filename"] = fileName;
            obj["filesize"] = fileSize;
            obj["chunkIndex"] = i;
            obj["totalChunks"] = totalChunks;
            obj["data"] = QString(chunk.toBase64());
            obj["button"] = Button;

            WriteToServer(obj);
        }
        file.close();
    }

//    cnt = 0;
//    while (1)
//    {
//        if (flag == 1)
//        {
//            break;
//        }
//        QThread::msleep(500);
//        cnt++;
//        qDebug() << "cnt:" << cnt << endl;
//    }


    // TCP有数据可读
    connect(socket, &QTcpSocket::readyRead, [this]()
    {
        buffer += socket->readAll(); // 读取来自tcp缓冲区的所有数据
        while (buffer.size() >= sizeof(size_t)) // 如果读取的数据大小大于包头，说明有需要读取的数据
        {
            size_t size = 0;
            memcpy(&size, buffer, sizeof(size_t)); // 真实数据大小
            if (buffer.size() < size + sizeof(size_t)) // 如果读取的数据大小小于真实数据大小和包头大小之和，说明真实数据没有传完
            {
                return; // 返回继续读取到buffer
            }
            QByteArray data = buffer.mid(sizeof(size_t), size); // 截取一次的json数据
            buffer.remove(0, size + sizeof(size_t)); // 把已读取的数据删去
//            process(data); // 处理json逻辑
            auto obj = QJsonDocument::fromJson(data).object(); // 解析Json数据，允许访问Json数据中的各个字段
            if (obj["flag"] == 12)
            {
                // 处理上传成功响应，更新上传进度
                QString filename = obj["filename"].toString();
                int chunkIndex = obj["chunkIndex"].toInt();
                int totalChunks = obj["totalChunks"].toInt();
                qDebug() << filename << chunkIndex << totalChunks << endl;
                qDebug() << "上传信息成功:" << chunkIndex << endl;
                // 计算并发送进度更新信号
                int progress = chunkIndex;
                emit progressChanged(progress);
                if (chunkIndex == 0)
                {
                    emit showload();
                }
            }
            else if (obj["flag"] == 7)
            {
                QString filename = obj["filename"].toString();
                emit showInfo(filename);
        //        quit();
            }
        }
    });
#endif
#if 0
    // 客户端断开连接，退出事件循环
    connect(this, &MyThread::showInfo, &loop, &QEventLoop::quit);

    loop.exec();//开启事件循环，阻塞线程
#endif
}

void MyThread::WriteToServer(const QJsonObject &obj)
{
    if (isConnected)
    {
        auto data = QJsonDocument(obj).toJson();
        size_t size =  data.size(); // 获取数据(data)的长度
        socket->write((char*)&size,sizeof(size_t)); // 将数据长度写入套接字(告诉接收方数据多长)
        socket->write(data); // 将Json数据写入套接字
        socket->flush(); // 强制刷新缓冲区
    }
}

void MyThread::process(const QByteArray &data)
{
    auto obj = QJsonDocument::fromJson(data).object(); // 解析Json数据，允许访问Json数据中的各个字段
    if (obj["flag"] == 12)
    {
        // 处理上传成功响应，更新上传进度
        QString filename = obj["filename"].toString();
        int chunkIndex = obj["chunkIndex"].toInt();
        int totalChunks = obj["totalChunks"].toInt();
        qDebug() << filename << chunkIndex << totalChunks << endl;
        qDebug() << "上传信息成功:" << chunkIndex << endl;
        // 计算并发送进度更新信号
        int progress = chunkIndex;
        emit progressChanged(progress);
        if (chunkIndex == 0)
        {
            emit showload();
        }
    }
    else if (obj["flag"] == 7)
    {
        QString filename = obj["filename"].toString();
        emit showInfo(filename);
        flag = 1;
//        quit();
    }
    else if (obj["flag"] == 8)
    {
        QString filepath = obj["desfilepath"].toString();
        QString filename = obj["filename"].toString();
        int chunkIndex = obj["chunkIndex"].toInt();
        int totalChunks = obj["totalChunks"].toInt();
        qDebug() << fromName << filename << chunkIndex << totalChunks << endl;
        QByteArray fileData = QByteArray::fromBase64(obj["data"].toString().toUtf8());

        QFile file(filepath + "/" + filename);
        if (file.exists())
        {
//            qDebug() << "文件已存在" << endl;
        }

        if (chunkIndex == 0)
        {
            file.open(QIODevice::WriteOnly);
        }
        else
        {
            file.open(QIODevice::Append);
        }

        if (file.isOpen())
        {
            file.write(fileData);
            file.close();
            if (chunkIndex == totalChunks - 1)
            {
                QJsonObject obj;
                obj["flag"] = 13;
                obj["fromname"] = fromName;
                obj["filename"] = filename;
                qDebug() << "File received successfully:" << filename;
            }
        }
    }
}

void MyThread::onConnected()
{
    qDebug() << "连接成功" << socket << endl;
    isConnected = true;
#if 1
    if(transferType == Upload)
    {
//        if (file.open(QIODevice::ReadOnly))
        {
            totalChunks = static_cast<int>(fileSize / chunkSize);
            if (fileSize % chunkSize != 0)
            {
                totalChunks++;
            }
            qDebug() << totalChunks << endl;

            int startChunk = this->startChunk;
            qDebug() << startChunk << endl;
            file.seek(startChunk * chunkSize);

            for (int i = startChunk; i < totalChunks; i++)
            {
                qDebug() << i << endl;
                QByteArray chunk = file.read(chunkSize);
                QJsonObject obj;
                obj["flag"] = 7;
                obj["fromname"] = fromName;
                obj["filename"] = fileName;
                obj["filesize"] = fileSize;
                obj["chunkIndex"] = i;
                obj["totalChunks"] = totalChunks;
                obj["data"] = QString(chunk.toBase64());
                obj["button"] = Button;

                WriteToServer(obj);
            }
            file.close();

            quit();
//            emit transferFinished();
        }
    }
    else
    {
        QJsonObject obj; // 构建Json对象
        obj["flag"] = 8; // 请求类型为LOGIN
        obj["fromname"] = fromName;
        obj["filename"] = fileName;
        obj["startChunk"] = startChunk;
        obj["desfilepath"] = filePath;
        WriteToServer(obj); // 发送到服务器
    }

    // TCP有数据可读
    connect(socket, &QTcpSocket::readyRead, [this]()
    {
        // 读取来自tcp缓冲区的所有数据
        buffer += socket->readAll();
        while (buffer.size() >= sizeof(size_t)) // 如果读取的数据大小大于包头，说明有需要读取的数据
        {
            size_t size = 0;
            memcpy(&size, buffer, sizeof(size_t)); // 真实数据大小
            if (buffer.size() < size + sizeof(size_t)) // 如果读取的数据大小小于真实数据大小和包头大小之和，说明真实数据没有传完
            {
                return; // 返回继续读取到buffer
            }
            QByteArray data = buffer.mid(sizeof(size_t), size); // 截取一次的json数据
            buffer.remove(0, size + sizeof(size_t)); // 把已读取的数据删去

            process(data); // 处理json逻辑
        }
    });
#endif
}
